package aggregate

import (
	"context"
	"slices"

	"gitee.com/leonscript/sally/v2/domain/entity"
	"gitee.com/leonscript/sally/v2/domain/strategy"
	"gitee.com/leonscript/sally/v2/infrastructure/utils"
	"gorm.io/gorm"
)

// ApprovalDecisionMaker 审批决策器
// 统一管理审批策略和自动审批策略的交互逻辑，解决策略间的耦合问题
type ApprovalDecisionMaker struct {
	approvalStrategyFactory     *strategy.ApprovalStrategyFactory
	autoApprovalStrategyFactory *strategy.AutoApprovalStrategyFactory
	reference                   Reference
}

// NewApprovalDecisionMaker 创建审批决策器
func NewApprovalDecisionMaker(reference Reference) *ApprovalDecisionMaker {
	return &ApprovalDecisionMaker{
		approvalStrategyFactory:     &strategy.ApprovalStrategyFactory{},
		autoApprovalStrategyFactory: &strategy.AutoApprovalStrategyFactory{},
		reference:                   reference,
	}
}

// DecisionParams 决策参数
type DecisionParams struct {
	CurrentUserID         string
	Workflow              entity.Workflow
	WorkflowTemplate      entity.WorkflowTemplate
	NextNodeReviewerTasks []entity.NodeReviewerTask
	Tx                    *gorm.DB
}

// AutoApprovalDecision 自动审批决策结果
type AutoApprovalDecision struct {
	// 需要自动审批的任务列表
	AutoApprovalTasks []AutoApprovalTask
}

// AutoApprovalTask 自动审批任务
type AutoApprovalTask struct {
	Task   entity.NodeReviewerTask
	Reason string
}

// NodeApprovalDecision 节点审批决策结果
type NodeApprovalDecision struct {
	ApprovalResult strategy.ApprovalResult
	Node           entity.Node
	NodeTemplate   entity.NodeTemplate
}

// MakeAutoApprovalDecision 做出自动审批决策
// 检查下一级审批任务中哪些需要自动审批
func (d *ApprovalDecisionMaker) MakeAutoApprovalDecision(ctx context.Context, params DecisionParams) (AutoApprovalDecision, error) {
	// 如果未启用自动审批，直接返回空结果
	if !params.WorkflowTemplate.EnableAutoApproval {
		return AutoApprovalDecision{}, nil
	}

	// 如果没有下一级审批任务，直接返回
	if len(params.NextNodeReviewerTasks) == 0 {
		return AutoApprovalDecision{}, nil
	}

	// 创建自动审批策略
	autoApprovalStrategy, err := d.autoApprovalStrategyFactory.CreateStrategy(strategy.AutoApprovalStrategy(params.WorkflowTemplate.AutoApprovalStrategy))
	if err != nil {
		return AutoApprovalDecision{}, err
	}

	// 获取决策所需的数据
	decisionData, err := d.buildAutoApprovalDecisionData(ctx, params)
	if err != nil {
		return AutoApprovalDecision{}, err
	}

	autoApprovalTasks := []AutoApprovalTask{}

	// 对每个下一级审批任务进行自动审批检查
	for _, nextTask := range params.NextNodeReviewerTasks {
		autoApprovalResult := autoApprovalStrategy.ShouldAutoApprove(
			ctx,
			params.CurrentUserID,
			decisionData.CompletedReviewerTasks,
			decisionData.NextNodeAllReviewerTasks,
			decisionData.NextNodeTemplate.GetApprovalStrategy(),
			params.NextNodeReviewerTasks,
			d, // 传入决策器实例
		)

		if autoApprovalResult.ShouldAutoApprove {
			autoApprovalTasks = append(autoApprovalTasks, AutoApprovalTask{
				Task:   nextTask,
				Reason: autoApprovalResult.Reason,
			})
		}
	}

	return AutoApprovalDecision{
		AutoApprovalTasks: autoApprovalTasks,
	}, nil
}

// MakeNodeApprovalDecision 做出节点审批决策
// 根据当前任务的审批结果，决定节点是否通过、拒绝或继续等待
func (d *ApprovalDecisionMaker) MakeNodeApprovalDecision(ctx context.Context, nodeReviewerTask entity.NodeReviewerTask, isPass bool, tx *gorm.DB) (NodeApprovalDecision, error) {
	// 获取节点信息
	node, err := d.reference.QueryNodeByIDTX(ctx, nodeReviewerTask.NodeID, tx)
	if err != nil {
		return NodeApprovalDecision{}, err
	}

	// 获取节点模板信息
	nodeTemplate, err := d.reference.QueryNodeTemplateByID(ctx, node.NodeTemplateID)
	if err != nil {
		return NodeApprovalDecision{}, err
	}

	// 创建审批策略
	approvalStrategy, err := d.approvalStrategyFactory.CreateStrategy(nodeTemplate.GetApprovalStrategy())
	if err != nil {
		return NodeApprovalDecision{}, err
	}

	// 查询该节点的所有审批任务
	allTasks, err := d.reference.QueryNodeReviewerTasksByNodeIDTX(ctx, nodeReviewerTask.NodeID, tx)
	if err != nil {
		return NodeApprovalDecision{}, err
	}

	// 执行审批策略
	approvalResult := approvalStrategy.HandleApproval(ctx, nodeReviewerTask, allTasks, isPass, d)

	return NodeApprovalDecision{
		ApprovalResult: approvalResult,
		Node:           node,
		NodeTemplate:   nodeTemplate,
	}, nil
}

// autoApprovalDecisionData 自动审批决策所需的数据
type autoApprovalDecisionData struct {
	CompletedReviewerTasks   []entity.NodeReviewerTask
	NextNodeAllReviewerTasks []entity.NodeReviewerTask
	NextNodeTemplate         entity.NodeTemplate
}

// buildAutoApprovalDecisionData 构建自动审批决策所需的数据
func (d *ApprovalDecisionMaker) buildAutoApprovalDecisionData(ctx context.Context, params DecisionParams) (autoApprovalDecisionData, error) {
	// 查询工作流中所有已完成的任务
	completedTasks, err := d.reference.QueryNodeReviewTasksTX(ctx, GetNodeReviewTasksRequest{
		WorkflowID: params.Workflow.ID,
	}, params.Tx)
	if err != nil {
		return autoApprovalDecisionData{}, err
	}

	// 过滤出已通过的任务
	passedTasks := make([]NodeReviewTask, 0)
	for _, task := range completedTasks {
		if task.Status == entity.TaskPassedStatus {
			passedTasks = append(passedTasks, task)
		}
	}

	// 转换为NodeReviewerTask类型
	completedReviewerTasks, err := utils.ArrayCopy(ctx, entity.NodeReviewerTask{}, passedTasks)
	if err != nil {
		return autoApprovalDecisionData{}, err
	}

	// 获取下一级节点信息
	nextNode, err := d.reference.QueryNodeByIDTX(ctx, params.NextNodeReviewerTasks[0].NodeID, params.Tx)
	if err != nil {
		return autoApprovalDecisionData{}, err
	}

	// 获取下一级节点模板信息
	nextNodeTemplate, err := d.reference.QueryNodeTemplateByID(ctx, nextNode.NodeTemplateID)
	if err != nil {
		return autoApprovalDecisionData{}, err
	}

	// 查询下一级节点的所有审批任务
	nextNodeAllTasks, err := d.reference.QueryNodeReviewerTasksByNodeIDTX(ctx, params.NextNodeReviewerTasks[0].NodeID, params.Tx)
	if err != nil {
		return autoApprovalDecisionData{}, err
	}

	// 转换为NodeReviewerTask类型
	nextNodeAllReviewerTasks, err := utils.ArrayCopy(ctx, entity.NodeReviewerTask{}, nextNodeAllTasks)
	if err != nil {
		return autoApprovalDecisionData{}, err
	}

	return autoApprovalDecisionData{
		CompletedReviewerTasks:   completedReviewerTasks,
		NextNodeAllReviewerTasks: nextNodeAllReviewerTasks,
		NextNodeTemplate:         nextNodeTemplate,
	}, nil
}

// WouldNodePassWithUserApproval 判断指定用户的审批是否会导致节点通过
// 这是一个通用方法，用于解决策略间的耦合问题
func (d *ApprovalDecisionMaker) WouldNodePassWithUserApproval(
	userID string,
	allTasks []entity.NodeReviewerTask,
	approvalStrategy entity.ApprovalStrategy,
) bool {
	// 检查用户是否在当前节点的审批任务中
	userTaskIndex := slices.IndexFunc(allTasks, func(task entity.NodeReviewerTask) bool {
		return task.ReviewerID == userID
	})

	// 如果用户不在当前节点的审批任务中，则不会导致节点通过
	if userTaskIndex == -1 {
		return false
	}

	userTask := &allTasks[userTaskIndex]

	// 如果用户的任务已经完成，则不会再次导致节点通过
	if userTask.Status != entity.TaskUnderReviewStatus {
		return false
	}

	// 根据审批策略判断
	switch approvalStrategy {
	case entity.ApprovalStrategyOr:
		// OR策略：任意一人通过即可通过整个节点
		return true

	case entity.ApprovalStrategyAnd:
		// AND策略：所有人通过才能通过整个节点
		// 需要检查除当前用户外的其他人是否都已经通过
		for _, task := range allTasks {
			if task.ReviewerID != userID {
				// 如果有其他人还未通过，则当前用户通过也不会导致节点通过
				if task.Status != entity.TaskPassedStatus {
					return false
				}
			}
		}
		// 所有其他人都已经通过，当前用户通过会导致节点通过
		return true

	default:
		// 默认按OR策略处理
		return true
	}
}

// CountPassedTasks 统计已通过的任务数量（包括指定的当前任务）
// 这是一个通用方法，用于解决策略间的重复逻辑
func (d *ApprovalDecisionMaker) CountPassedTasks(
	currentTask entity.NodeReviewerTask,
	allTasks []entity.NodeReviewerTask,
	isCurrentTaskPass bool,
) (passedCount int, totalCount int) {
	totalCount = len(allTasks)
	passedCount = 0

	// 统计已通过的任务数量
	for _, task := range allTasks {
		if task.ID == currentTask.ID {
			// 当前任务的状态
			if isCurrentTaskPass {
				passedCount++
			}
		} else if task.Status == entity.TaskPassedStatus {
			// 其他已通过的任务
			passedCount++
		}
	}

	return passedCount, totalCount
}
